from django.shortcuts import render
from django.views import View
from django import http
import json,pickle,base64
from django_redis import get_redis_connection

from goods.models import SKU
from meid_duo.utils.response_code import RETCODE
# Create your views here.


class CartsView(View):

    def post(self,request):
        """添加购物车"""
        #  获取数据，请求体
        json_dict = json.loads(request.body.decode())
        sku_id = json_dict.get("sku_id")
        count = json_dict.get("count")
        selected = json_dict.get('selected','True')
        #  检验
        if not all([sku_id,count]):
            return http.HttpResponseForbidden("缺少必传参数")
        # 查询此id是否存在
        try:
            sku = SKU.objects.get(id=sku_id)
        except SKU.DoesNotExist:
            return http.HttpResponseForbidden("sku不存在")

        user = request.user

        # 登录用户添加购物车数据到redis数据库
        if user.is_authenticated:
            """    redis数据库存储格式
            hash: {sku_id_1: count, sku_id2: count}
            set: {sku_id_1, sku_id_2}
            """
            redis_conn = get_redis_connection('carts')  # 连接数据库
            pl = redis_conn.pipeline()  # 管道
            # hincrby()   该函数自动完成相同商品的累加，并存在数据库中
            pl.hincrby('carts_%s' % user.id, sku_id, count)
            if selected:   # 将勾选了的商品sku id存在数据库中
                pl.sadd('selected_%s' % user.id, sku_id)
            pl.execute()  # 执行
            return http.JsonResponse({"code":RETCODE.OK,"errmsg":"OK"})

        # 未登录用户添加购物车通过浏览器存储在cookies中
        else:

            """    存储在cookies中的数据格式
            {
                sku_id_1: {'count': 2, 'selected': True},
                sku_id_2: {'count': 2, 'selected': True}
            }
            """
            # 检查判断购物车中是否已有数据
            cart_str = request.COOKIES.get('carts') # 获取cookies
            if cart_str:  # 如果上一步有获取到值，则将数据格式转化为字典，方便后面使用
                cart_str_bytes = cart_str.encode()
                cart_str_base = base64.b64decode(cart_str_bytes)
                cart_dict = pickle.loads(cart_str_base)

                # pickle.loads(base64.b64decode(cart_str.encode()))
            else:  # 没有购物车数据则创建空字典
                cart_dict = {}
            # 购物车数据累加，主要是count的累加，如果数据库中已有数据，则count数据累加，
            if sku_id in cart_dict:
                origin_count = cart_dict[sku_id]['count']
                count += origin_count

            cart_dict[sku_id] ={   # 有则覆盖，无则创建
                'count':count,
                'selected':selected
            }
            # 解码，将字典转换为cookies中的字符串
            cart_dict = base64.b64encode(pickle.dumps(cart_dict)).decode()
            response = http.JsonResponse({"code":RETCODE.OK,"errmsg":"ok"})
            response.set_cookie("carts",cart_dict)
            return response

    def get(self,request):
        """展示购物车数据"""
        user = request.user  # 用户
        # 判断是否登录
        if user.is_authenticated:   # 已登录用户，redis数据库
            redis_conn = get_redis_connection("carts")
            redise_carts = redis_conn.hgetall('carts_%s' % user.id)
            redis_select = redis_conn.smembers('selected_%s' % user.id)
            carts_dict = {}
            # 将redis数据格式转换拼接成与cookies数据格式一样，方便在返回数据给前端时使用
            for sku_id,count in redise_carts.items():
                carts_dict[int(sku_id)] = {
                    'count':int(count),
                    'selected':sku_id in redis_select
                }

            """登录用户获取redis购物车数据
            hash: {sku_id_1: count, sku_id2: count}
            set: {sku_id_1, sku_id_2}
            """

        else:
            """未登录用户获取cookie购物车数据"""
            carts_str = request.COOKIES.get('carts')
            if carts_str:  # 取道数据则格式转化
                # carts_dict = pickle.loads(base64.b64decode(carts_str.encode()))
                carts_dict = pickle.loads(base64.b64decode(carts_str.encode()))
            else:
                return render(request, 'cart.html')
        # 查询已添加购物车的所有sku
        sku_qs = SKU.objects.filter(id__in=carts_dict.keys())

        carts_skus = []  # 返回前端的数据
        for sku in sku_qs:  #  数据的包装
            sku_dict = {
                'id': sku.id,
                'name':sku.name,
                'price':str(sku.price),
                'default_image_url':sku.default_image.url,
                # 'count':carts_dict[sku.id]['count'],
                'count': int(carts_dict[sku.id]['count']),
                'selected':str(carts_dict[sku.id]['selected']),
                'amount':str(sku.price * int(carts_dict[sku.id]['count']))
            }
            carts_skus.append(sku_dict)
        context ={
            "cart_skus":carts_skus
        }
        return render(request, 'cart.html', context)


    def put(self,request):
        """购物车数据的修改"""
        # 参考购物车添加，修改与添加区别： 修改即在添加的基础上，有则覆盖，无则新增
        # 数据获取
        json_dict = json.loads(request.body.decode())
        sku_id = json_dict.get("sku_id")
        count = json_dict.get("count")
        selected = json_dict.get('selected')
        #

        # 校验
        if not all([sku_id, count]):
            return http.HttpResponseForbidden("缺少必传参数")

        try:
            sku = SKU.objects.get(id=sku_id)
        except SKU.DoesNotExist:
            return http.HttpResponseForbidden("sku不存在")

        user = request.user
        # 需要返回的数据及包装  （写在判断用户是否登录前，即不管是否登录，在返回数据时都可以使用）
        cart_skus = {
            'id': sku.id,
            'name': sku.name,
            'price': sku.price,
            'default_image_url': sku.default_image.url,
            'count': int(count),
            'selected': selected,
            'amount': sku.price * int(count)
        }
        response = http.JsonResponse({'code': RETCODE.OK, 'errmsg': '修改购物车数据成功', 'cart_sku': cart_skus})
        if user.is_authenticated:  #  登录用户，连接使用redis数据库获取数据
            redis_conn = get_redis_connection("carts")
            pl = redis_conn.pipeline()
            pl.hset("carts_%s" % user.id,sku_id,count)  # 设置数据，即前端修改的数据
            if selected:  # 判断是否修改selected，即判断前端是否勾选
                pl.sadd('selected_%s' % user.id, sku_id)
            else:
                pl.srem('selected_%s' % user.id, sku_id)
            pl.execute()
            # return http.JsonResponse({"code":RETCODE.OK,"errmsg":"OK"})
        else:  # 未登录用户使用cookies
            cart_str = request.COOKIES.get("carts")
            if cart_str:
                cart_dict = pickle.loads(base64.b64decode(cart_str.encode()))
            else:
                return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': 'cookie数据没有获取'})
            cart_dict[sku_id]={
                'count':count,
                'selected':selected
            }
            cart_str = base64.b64encode(pickle.dumps(cart_dict)).decode()
            # cart_skus = {
            #     'id': sku.id,
            #     'name': sku.name,
            #     'price': sku.price,
            #     'default_image_url': sku.default_image.url,
            #     'count': int(count),
            #     'selected': selected,
            #     'amount': sku.price * int(count)
            # }

            # response = http.JsonResponse({'code': RETCODE.OK, 'errmsg': '修改购物车数据成功', 'cart_sku': cart_skus})
            response.set_cookie("carts",cart_str)
        return response


    #   未写
    # def delete(self, request):
    #     """删除购物车数据"""
    #     # 接收sku_id
    #     json_dict = json.loads(request.body.decode())
    #     sku_id = json_dict.get('sku_id')
    #     # 校验
    #     try:
    #         sku = SKU.objects.get(id=sku_id)
    #     except SKU.DoesNotExist:
    #         return http.HttpResponseForbidden('sku不存在')
    #
    #     # 判断是否登录
    #     user = request.user
    #     response = http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK'})
    #
    #     if user.is_authenticated:
    #         # 登录操作redis数据
    #         # 创建redis连接对象
    #         redis_conn = get_redis_connection('carts')
    #         # 创建管道
    #         pl = redis_conn.pipeline()
    #
    #         # 删除hash中的sku_id及count
    #         pl.hdel('carts_%s' % user.id, sku_id)
    #         # 删除set集合中的勾选
    #         pl.srem('selected_%s' % user.id, sku_id)
    #         pl.execute()
    #
    #     else:
    #         # 未登录操作cookie数据
    #         # 获取cookie数据
    #         cart_str = request.COOKIES.get('carts')
    #
    #         # 判断cookie是否获取到
    #         if cart_str:
    #             # 把字符串转换成字典
    #             cart_dict = pickle.loads(base64.b64decode(cart_str.encode()))
    #         else:
    #             # 没有获取cookie数据 直接返回
    #             return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': 'cookie没有获取到'})
    #         # 判断当前要删除的sku_id在字典中是否存在
    #         if sku_id in cart_dict:
    #             # del cart_dict[sku_id]
    #             del cart_dict[sku_id]
    #
    #         if len(cart_dict.keys()) == 0:  # 如果cookie中的购物车数据已经删除完了
    #             response.delete_cookie('carts')  # 删除cookie
    #             # return response
    #
    #
    #         # 将字典转换成字符串
    #         cart_str = base64.b64encode(pickle.dumps(cart_dict)).decode()
    #         # 设置cookie
    #         response.set_cookie('carts', cart_str)
    #     # 响应
    #     return response
    def delete(self,request):
        """删除购物车"""
        # 数据获取
        json_dict = json.loads(request.body.decode())
        sku_id = json_dict.get('sku_id')
        # 校验
        try:
            sku = SKU.objects.get(id=sku_id)
        except SKU.DoesNotExist:
            return http.HttpResponseForbidden("sku不存在")

        user = request.user
        response = http.JsonResponse({"code": RETCODE.OK, "errmsg": "OK"})
        if user.is_authenticated: # 登录用户的redis数据库使用
            redis_conn = get_redis_connection('carts')
            pl = redis_conn.pipeline()
            pl.hdel('carts_%s' % user.id, sku_id)
            pl.srem('selected_%s' % user.id, sku_id)
            pl.execute()
            # return http.JsonResponse({"code":RETCODE.OK,"errmsg":'OK'})

        else: # 未登录用户的cookies使用
            cart_str = request.COOKIES.get('carts')
            if cart_str:
                cart_dict = pickle.loads(base64.b64decode(cart_str.encode()))
            else:
                return http.JsonResponse({"code":RETCODE.SESSIONERR,"errmsg":"未取到cookies"})
            if sku_id in cart_dict:
                del cart_dict[sku_id]

            if len(cart_dict)==0:  # 若购物车中无数据，整个cook删除
                # response = http.JsonResponse({"code": RETCODE.OK, "errmsg": "OK"})
                # delete_cookie使用后，下面的设置cookies不加时限，则无效
                response.delete_cookie("carts",cart_str)
                # return response

            cart_str = base64.b64encode(pickle.dumps(cart_dict)).decode()

            # response = http.JsonResponse({"code":RETCODE.OK,"errmsg":"OK"})
            response.set_cookie("carts",cart_str)
        return response



class CartsSelectView(View):
    """全选购物车"""
    def put(self,request):
        # 数据获取
        json_dict = json.loads(request.body.decode())
        selected = json_dict.get('selected')
        # 校验
        if isinstance(selected,bool) is False:
            return http.HttpResponseForbidden("参数有误")

        user = request.user
        response = http.JsonResponse({"code":RETCODE.OK,"errmsg":"OK"})
        if user.is_authenticated:
            redis_conn = get_redis_connection('carts')
            redis_carts = redis_conn.hgetall('carts_%s' % user.id)
            if selected:
                redis_conn.sadd('selected_%s' % user.id, *redis_carts.keys())
            else:
                redis_conn.delete('selected_%s' % user.id)

        else:
            carts_str = request.COOKIES.get('carts')
            if carts_str:
                carts_dict = pickle.loads(base64.b64decode(carts_str.encode()))
            else:
                return http.HttpResponseForbidden("未取道数据")
            for sku_id in carts_dict:
                carts_dict[sku_id]['selected'] = selected

            carts_str = base64.b64encode(pickle.dumps(carts_dict)).decode()
            response.set_cookie('carts',carts_str)
        return response


class CartsSimpleView(View):
    """简单购物车数据显示"""
    # 参考购物车展示
    def get(self,request):
        user = request.user
        if user.is_authenticated:
            redis_conn = get_redis_connection('carts')
            redis_dict = redis_conn.hgetall("carts_%s" % user.id)
            redis_ids = redis_conn.smembers('selected_%s' % user.id)
            cart_dict = {}
            for sku_id,count in redis_dict.items():
                cart_dict[int(sku_id)]={
                    'count':int(count),
                    'select':sku_id in redis_ids
                }
        else:
            cart_str = request.COOKIES.get('carts')
            if cart_str:
                # 将字符串转换成字典
                cart_dict = pickle.loads(base64.b64decode(cart_str.encode()))
            else:
                return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '没有购物车数据'})
        sku_qs = SKU.objects.filter(id__in=cart_dict.keys())
        cart_skus=[]
        for sku in sku_qs:
            sku_dict={
                'id':sku.id,
                'name':sku.name,
                'price':sku.price,
                'default_image_url':sku.default_image.url,
                'count':int(cart_dict[sku.id]['count'])
            }
            cart_skus.append(sku_dict)
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'cart_skus': cart_skus})











